﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Aeon.Configuration;

namespace Aeon.Emulator.Launcher
{
    /// <summary>
    /// Maintains copies of drive configurations and views.
    /// </summary>
    public sealed class ConfigViewCache : INotifyPropertyChanged
    {
        private Dictionary<DriveConfigurationInfo, IDriveConfigurationView> configs = new Dictionary<DriveConfigurationInfo, IDriveConfigurationView>();
        private DriveConfigurationInfo selectedType;

        /// <summary>
        /// Initializes a new instance of the ConfigViewCache class.
        /// </summary>
        /// <param name="defaultConfiguration">Default configuration instance.</param>
        public ConfigViewCache(IDriveConfiguration defaultConfiguration)
        {
            if(defaultConfiguration != null)
            {
                var info = (from i in LauncherEnvironment.ConfigurationMapper.DriveConfigurations
                            where i.ConfigType == defaultConfiguration.GetType()
                            select i).First();

                var view = info.CreateView();
                view.DriveConfiguration = defaultConfiguration;
                this.configs.Add(info, view);
                this.selectedType = info;
            }
        }
        
        /// <summary>
        /// Occurs when a property value has changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Gets or sets the current configuration type.
        /// </summary>
        public DriveConfigurationInfo SelectedType
        {
            get
            {
                return this.selectedType;
            }
            set
            {
                if(value != this.selectedType)
                {
                    this.selectedType = value;
                    this.OnPropertyChanged(new PropertyChangedEventArgs("SelectedType"));
                    this.OnPropertyChanged(new PropertyChangedEventArgs("SelectedConfigurationView"));
                }
            }
        }
        /// <summary>
        /// Gets the current configuration view.
        /// </summary>
        public IDriveConfigurationView SelectedConfigurationView
        {
            get
            {
                IDriveConfigurationView view;
                if(this.configs.TryGetValue(this.SelectedType, out view))
                    return view;
                else if(this.SelectedType != null)
                {
                    var config = this.SelectedType.CreateConfiguration();
                    view = this.SelectedType.CreateView();
                    view.DriveConfiguration = config;
                    this.configs.Add(this.SelectedType, view);
                    return view;
                }
                else
                    return null;
            }
        }

        /// <summary>
        /// Raises the PropertyChanged event.
        /// </summary>
        /// <param name="e">Information about the event.</param>
        private void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;
            if(handler != null)
                handler(this, e);
        }
    }
}
